home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / checklpt.arc / COPYLPT.C < prev    next >
Text File  |  1987-04-30  |  15KB  |  313 lines

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /* Program copylpt                                                         */
  4. /*                                                                         */
  5. /* Usage: copylpt filename [PRINTER]                                       */
  6. /*        where filename is file to be copied (upper, lower or mixed case) */
  7. /*        and optional argument PRINTER is the printer to copy to          */
  8. /*           (upper, lower or mixed case)                                  */
  9. /*           PRN, 1 or LPT1 for LPT1,                                      */
  10. /*           2 or LPT2 for LPT2 or                                         */
  11. /*           3 or LPT3 for LPT3.                                           */
  12. /*        If PRINTER is not specified, copy to LPT1                        */
  13. /* Returns ERRORLEVEL     0 if file filename was copied to the printer     */
  14. /*                        1 if PRINTER is not available                    */
  15. /*                        2 if PRINTER is available, but file filename is  */
  16. /*                          not available.                                 */
  17. /*                        3 if both PRINTER and file filename are          */
  18. /*                          available, but there was some error copying    */
  19. /*                          filename to PRINTER.                           */
  20. /*                      100 for certain system errors.                     */
  21. /*                                                                         */
  22. /*    I designed copylpt to copy a file to a printer if the printer        */
  23. /* is available and then inform a batch file of its success or failure.    */
  24. /* I wanted my AUTOEXEC.BAT file to copy an user-defined character set to  */
  25. /* my Epson printer if possible without stopping for a critical error if   */
  26. /* the printer is off.                                                     */
  27. /*    If the filename's path does not start with a back slash and it does, */
  28. /* not specify a drive, copylpt looks first at the filename itself, then   */
  29. /* appends it to any paths specified in a PATH-like environment variable   */
  30. /* which has the same name as the filename's extension, then appends it to */
  31. /* any paths in the PATH enviroment variable.  Under DOS 3 or later, it    */
  32. /* finally appends it to the calling program's drive and path.             */
  33. /*    copylpt requires DOS 2.0 or later to run.                            */
  34. /*    The ERRORLEVEL of 100 occurs only in the event of a compiler or      */
  35. /* system failure.                                                         */
  36. /*                                                                         */
  37. /*    I compiled copylpt and its subfunctions for use with Lattice C,      */
  38. /*  Version 3.  Some of their features which may not be portable are:      */
  39. /*    _DOS is a Lattice C system variable which contains the DOS major     */
  40. /* version.                                                                */
  41. /*    fileno() is an UNIX function which returns the file handle for a     */
  42. /* file pointer.                                                           */
  43. /*    Lattice classes onerror(action) as a MSDOS function.  onerror(1)     */
  44. /* preeempts the MSDOS critical error handler.  onerror(0) restores the    */
  45. /* MSDOS critical error handler.                                           */
  46. /*    getfc(fh, cw) returns 0 if fh is a valid file handle, -1 otherwise.  */
  47. /* If it is a valid file handle, the function sets cw to the               */
  48. /* word for the file.  Bit 7 is 0 for a disk file.  See DOS interrupt 44H, */
  49. /* AL = 0, for more information about the characteristic word              */
  50. /*    union REGS is a Lattice union which lets the registers become        */
  51. /* arguments to functions which invoke 8086 interrupts.  Two functions     */
  52. /* use it. Both return an int containing the flags after the interrupt.    */
  53. /* intdos invokes interrupt 21H with input registers as the first          */
  54. /* argument and returns the value of the registers after the interrupt as  */
  55. /* the second argument.  int86 invokes the interrupt specified by the      */
  56. /* first argument with input registers as the second argument.  It returns */
  57. /* the value of the registers after the interrupt as the third argument.   */
  58. /*    fopene is a Lattice 3 variant version of fopen which automatically   */
  59. /* searches the environment as described above.                            */
  60. /*    stcgfn and stcgfp are Lattice expressions which get a file name      */
  61. /* node (name and extension) and path respectively to string variables.    */
  62. /* The path does not have a trailing "\"                                   */
  63. /*   Lattice function getdsk returns 0 if the default drive is A:,         */
  64. /* 1 if it is B:, etc.                                                     */
  65. /*    Lattice function getcd takes a drive number as its first argument,   */
  66. /* with 0 for the default drive, 1 for A:, etc.  It returns the current    */
  67. /* directory in the variable pointed at by its second argument.  The       */
  68. /* current directory does not include either the drive letter or the       */
  69. /* trailing back-slash.  In particular, it returns an empty string for     */
  70. /* the root directory.                                                     */
  71. /*    dfind is a Lattice implementation of the DOS function which returns  */
  72. /* the directory entry which matches the input file name.  Sets the DOS    */
  73. /* information in a structure which has a type FILEINFO, and it returns    */
  74. /* 0 if it can make a match, -1 otherwise.                                 */
  75. /*    getenv(name) is a Lattice C function which returns a pointer to the  */
  76. /* information following the = sign in the DOS environment string of the   */
  77. /* form NAME=information.                                                  */
  78. /*    strupr converts a string to upper case.                              */
  79. /*    Lattice C sets a variable errno to a non-zero value if a standard    */
  80. /* library function detects an error.  It never automatically resets       */
  81. /* errno.  Errno is in error.h.                                            */
  82. /*                                                                         */
  83. /*    Full identifiers in this program conform to the proposed ANSI        */
  84. /* standard of at most 31 significant characters, and they are different   */
  85. /* within the first 8 characters.  Lattice C includes a -n compiler        */
  86. /* switch which changes the number of significant characters in            */
  87. /* identifiers from 8 to 39.  While this program works without it, I       */
  88. /* designed them to use it.                                                */
  89. /*                                                                         */
  90. /*      This file requires the functions in files CHECKLPT.C and FOPEN1.C  */
  91. /* to compile and run                                                      */
  92. /*                                                                         */
  93. /* Lew Paper                                                               */
  94. /* 4/18/87                                                                 */
  95. /***************************************************************************/
  96.  
  97. #include <stdio.h>
  98. #include <ctype.h>
  99. #include <string.h>
  100. #include <dos.h>
  101. #include <error.h>
  102. #include <stdlib.h>
  103.  
  104. extern char _DOS;                   /* Lattice system variable.  DOS major */
  105.                                     /* version number                      */
  106.  
  107.    static int printer_number = 1;
  108.    static char printer_name[] = "LPT1";
  109.    static FILE *printer_fp;
  110.    static int handle;
  111.  
  112.    static char file_name[65];
  113.    static FILE *file_fp;
  114.  
  115.    extern int errno;                   /* fgetc sets this to non-zero      */
  116.    static char error_message_end[90];  /* Pointer to end of error message  */
  117.  
  118. /* Prototypes for external functions                                       */
  119.    int handle_check_lpt_available(int);
  120.    FILE *fopene_program(char *, char *, char *);
  121.  
  122. #define CHECK_NAME(LEGAL) !strcmpi(argv[2], "LEGAL")
  123. #define CALLING_NAME argv[0]
  124. #define CARRY_FLAG 1
  125.  
  126. static void close_device()
  127.  
  128. {
  129.    if (fclose(printer_fp))
  130.       fprintf(stderr, "\nError in closing printer %s\n\n", printer_name);
  131. }
  132.  
  133. static void close_file()
  134.  
  135. {
  136.    if (fclose(file_fp))
  137.       fprintf(stderr, "\nError in closing file %s\n\n", file_name);
  138. }
  139.  
  140.    /* Write an error message to stderr, close LPT2 or LPT3 and exit with   */
  141.    /* ERRORLEVEL = 1                                                       */
  142. static void no_copy_end()
  143.  
  144. {
  145.    fprintf(stderr, "Unable to copy file %s\nto printer %s because",
  146.            file_name, printer_name);
  147.    fputs(error_message_end, stderr);
  148.    fputs("\n\n", stderr);
  149.    if (printer_number > 1)
  150.       close_device();
  151. }
  152.  
  153. static void write_printer_error()
  154.  
  155. {
  156.    close_file();                       /* Close input file                 */
  157.    sprintf(error_message_end, " Error writing to printer %s",
  158.            printer_name);
  159.    no_copy_end();
  160.    exit(3);
  161. }
  162.  
  163. static void usage()
  164.  
  165. {
  166.    fputs("Usage: copylpt filename [PRINTER]\n", stderr);
  167.    fputs("       where filename is file to be copied ",stderr);
  168.    fputs("(upper, lower or mixed case)\n", stderr);
  169.    fputs("       and optional argument PRINTER is the printer to copy to\n",
  170.          stderr);
  171.    fputs("          (upper, lower or mixed case)\n", stderr);
  172.    fputs("          PRN, 1 or LPT1 for LPT1,\n", stderr);
  173.    fputs("          2 or LPT2 for LPT2 or\n", stderr);
  174.    fputs("          3 or LPT3 for LPT3.\n", stderr);
  175.    fputs("       If PRINTER is not specified, copy to LPT1\n", stderr);
  176.    fputs("Returns ERRORLEVEL   0 if file filename was copied to the printer\n",
  177.          stderr);
  178.    fputs("                     1 if file filename was not copied ", stderr);
  179.    fputs("to the printer\n", stderr);
  180.    fputs("                     100 for certain system errors.\n\n", stderr);
  181.  
  182.    exit(1);
  183. }                                      /* usage                            */
  184.  
  185. static void get_device_handle()
  186.  
  187. {
  188.    int cw;                             /* Characteristic word for file     */
  189.  
  190.    /*    PC DOS 3.1 opens printers which are off or not installed with     */
  191.    /* no error indication, so I can not test a critical error here.  I     */
  192.    /* preempted the critical error handler because I am not sure that      */
  193.    /* some version of DOS might not treat opening a printer which          */
  194.    /* doesn't exist as a critical error.                                   */
  195.    if (onerror(1))                     /* Preempt MSDOS critical error     */
  196.                                        /* handler.                         */
  197.    {
  198.       fputs("onerror(1) failed in get_device_handle\n\n", stderr);
  199.       exit(100);
  200.    }
  201.  
  202.    if (printer_number == 1)
  203.       printer_fp = freopen("LPT1", "wb", stdprt);
  204.    else
  205.       printer_fp = fopen(printer_name, "wb");
  206.    if (!printer_fp)
  207.    {
  208.       fprintf(stderr, "Unable to open device %s\n\n", printer_name);
  209.       exit(1);
  210.    }
  211.    
  212.    if (getfc((handle = fileno(printer_fp)), &cw) || !(cw & 0x0080))
  213.                                     /* Invalid handle                      */
  214.    {
  215.       fprintf(stderr, "There is no device driver %s installed\n\n",
  216.               printer_name);
  217.       close_device();
  218.       exit(1);
  219.    }
  220.  
  221.    /*    The Lattice C Manual doesn't say exactly how onerror() works.     */
  222.    /* I turned it off here to protect its being turned back on in          */
  223.    /* FILE_check_lpt_available                                             */
  224.    if (onerror(0))                     /* Restore MSDOS critical error     */
  225.    {
  226.       fputs("onerror(0) failed in get_device_handle\n\n", stderr);
  227.       close_device();
  228.       exit(100);
  229.    }
  230.  
  231. }                                      /* get_device_handle                */
  232.  
  233. main(argc, argv)
  234.    int argc;
  235.    char *argv[];
  236.  
  237. {
  238.    int c;
  239.  
  240.    /* Check for DOS 2.0 or later                                           */
  241.    if (!_DOS)
  242.    {
  243.       fputs("COPYLPT requires DOS 2.0 or later.\n\n", stderr);
  244.       exit(1);
  245.    }
  246.  
  247.    switch (argc)
  248.    {
  249.       case 1:                          /* No file name specified           */
  250.          usage();                      /* Display usage and exit with      */
  251.                                        /* ERRORLEVEL = 1.                  */
  252.       break;
  253.  
  254.       case 2:                          /* Default printer                  */
  255.       break;
  256.  
  257.       default:                         /* argc >= 3.  Set up printer name  */
  258.                                        /* and handle.                      */
  259.          if (CHECK_NAME(prn) || CHECK_NAME(1) || CHECK_NAME(lpt1))
  260.                                        /* Defensive programming.  LPT1 is  */
  261.                                        /* the original default printer, so */
  262.                                        /* these assignments are not        */
  263.                                        /* necessary.                       */
  264.             printer_number = 1;
  265.          else if (CHECK_NAME(2) || CHECK_NAME(lpt2))
  266.             printer_number = 2;
  267.          else if (CHECK_NAME(3) || CHECK_NAME(lpt3))
  268.             printer_number = 3;
  269.          else
  270.             usage();                   /* Display usage and exit with      */
  271.                                        /* ERRORLEVEL = 1.                  */
  272.          sprintf(printer_name, "LPT%d", printer_number);
  273.          break;
  274.    }
  275.  
  276.    get_device_handle();
  277.  
  278.    /* Transfer upper case of file name from argv[1] to file_name.          */
  279.    (void) strcpy(file_name, argv[1]);
  280.    (void) strupr(file_name);
  281.  
  282.    /* Check if printer is available */
  283.    if (handle_check_lpt_available(handle))
  284.    {
  285.       sprintf(error_message_end, " printer %s was not available",
  286.               printer_name);
  287.       no_copy_end();
  288.       exit(1);
  289.    }
  290.  
  291.    file_fp = fopene_program(file_name, "rb", CALLING_NAME);
  292. if (!file_fp)
  293.    {
  294.       sprintf(error_message_end, " file %s could not be opened",
  295.               file_name);
  296.       no_copy_end();
  297.       exit(2);
  298.    }
  299.  
  300.    errno = 0;                          /* Clear any prior errors           */
  301.    while ((c = getc(file_fp)) != EOF)
  302.       if (putc(c, printer_fp) == EOF)
  303.          write_printer_error();
  304.    if (errno)                          /* Check for input error            */
  305.       write_printer_error();
  306.  
  307.    close_file();
  308.    close_device();
  309.    fprintf(stderr, "copylpt wrote file %s to printer %s\n\n",
  310.            file_name, printer_name);
  311.  
  312. }                                      /* main                             */
  313.